'''
Purpose    :  extracts features from raw GNSS receiver measurement data
'''

import os
from datetime import datetime
import numpy as np
from joblib import Parallel, delayed
from matplotlib import pyplot as plt
from pandas import Series
from readnmea import readNMEA


def draw_hist(CN0List, Title, Xlabel, Ylabel, Xmin, Xmax, path, stat):
    '''
    Purpose    :  draw the CN0 distribution
    input      :  CN0List: the CN0 values of all satellites in the current file
                     stat: the statistics of the CN0 values
                     path: the path to save the figure
    '''
    plt.figure(figsize=(7, 5.3))
    _, ax = plt.subplots(figsize=(7, 5.3))
    plt.hist(CN0List, 120)
    plt.xlabel(Xlabel)
    plt.xlim(Xmin, Xmax)
    plt.ylabel(Ylabel)
    plt.title(Title)
    plt.text(0.05, 0.85,
             "mean:{:.4f},std:{:.4f}\nskew:{:.4f},kurt:{:.4f}\nmedian:{:.4f},iqr:{:.4f}".format(stat[0], stat[1], stat[4],
                                                                                                stat[5], stat[6], stat[7]),
             transform=ax.transAxes)
    plt.savefig(path, dpi=750, bbox_inches='tight')
    plt.show(block=True)


def draw_num_cn0(aveNum,aveCN0,Title,path):
    '''
    Purpose    :  draw the hist of the average number and CN0 of satellites by constellation
    input      :  aveNum: the average number of satellites by constellation
                  aveCN0: the average CN0 of satellites by constellation
    '''

    x_data = ['GP', 'GL', 'GA', 'GB', 'GQ'] # the constellations, GP for GPS, GL for GLONASS, GA for GALILEO, GB for BEIDOU, GQ for QZSS

    fig = plt.figure(figsize=(7, 4.9))
    ax = fig.add_subplot(111)
    #_, ax = plt.subplots(figsize=(7, 5.3))
    ax.set_ylim([0, 15])
    ax.set_yticks = np.arange(0, 15)
    ax.set_yticklabels = np.arange(0, 15)

    bar_width = 0.3
    ax.set_ylabel('SV num');
    ax.bar(x=np.arange(len(x_data)), width=bar_width, height=aveNum, label='SV num', fc='steelblue', alpha=0.8)

    for a, b in enumerate(aveNum):
        plt.text(a, b + 0.0005, '%.1f' % b, ha='center')

    ax1 = ax.twinx()

    ax1.set_ylim([0, 50])
    ax1.set_yticks = np.arange(0, 50)
    ax1.set_yticklabels = np.arange(0, 50)
    ax1.set_ylabel('Ave. CN0');
    ax1.bar(x=np.arange(len(x_data)) + bar_width, width=bar_width, height=aveCN0, label='Ave. CN0', fc='indianred',
                   alpha=0.8)

    for a, b in enumerate(aveCN0):
        plt.text(a + 0.3, b + 0.001, '%.4f' % b, ha='center')

    plt.xticks(np.arange(len(x_data)) + bar_width / 2, x_data)

    ax.set_xlabel('constellations')

    fig.legend(loc=1, bbox_to_anchor=(0.28, 1), bbox_transform=ax.transAxes)
    plt.title(Title)
    plt.savefig(path, dpi=750, bbox_inches='tight')
    plt.show(block=True)


def getFileName(filepath):
    '''
    Purpose    :  get the file names in the given folder
    input      :  filepath: the path of the folder
    '''
    pathList = os.listdir(filepath)
    PATH = []
    fileName = []
    i = -0
    for allFile in pathList:
        if allFile[:2] != "~$":
            everyFile = os.path.join(filepath, allFile)
            everyFile = everyFile.replace('\\', '/', 1)
            i = i + 1
            PATH.append(everyFile)
            fileName.append(allFile[:-4])
            print( str(i)+':'+everyFile)
    return PATH, fileName

def df2xlsx(path,resultPath):
    '''
    Purpose    :  convert the GNSS receiver measurements to xlsx files, and draw the CN0 distribution and the average number and CN0 of satellites by constellation (optional)
    input      :  path: the path of the GNSS receiver measurement file
            resultPath: the path to save the xlsx files and figures
    '''
    basename = os.path.basename(path)[:-4]
    if not os.path.exists(resultPath + basename + '.xlsx'):
        path_dataframe, allFreqCNO, label, SVnum, aveCNO = readNMEA(path)

        xx = Series(allFreqCNO)
        q75, q25 = np.percentile(xx, [75, 25])
        iqr = q75 - q25
        xt = [xx.mean(), xx.std(), xx.max(), xx.min(), xx.skew(), xx.kurt(), xx.median(), iqr]

        path_dataframe.to_excel(resultPath + basename + '.xlsx', sheet_name='sheet1')
        if draw:
            print('start draw')
            draw_hist(allFreqCNO,
                      f'CN0 distribution in {typess[label - 1]} scenario (total:{len(allFreqCNO)})' + '\n File:' + basename,
                      'CN0(dB-Hz)',
                      'Number of samples', min(allFreqCNO) - 1.5, max(allFreqCNO) + 1.5, resultPath + basename + '.pdf',
                      xt)


            draw_num_cn0(SVnum, aveCNO,
                         f'Ave. SV num. and CN0 in {typess[label - 1]} scenario ' + '\n File:' + basename,
                         resultPath + basename + 'numcno' + '.pdf')

def batchUbx2xlsx(sorcePath, resultPath):
    '''
    Purpose    :  convert the GNSS receiver measurements to xlsx files in batch
    input      :  sorcePath: the path of the GNSS receiver measurement files
                cresultPath: the path to save the xlsx files
    '''
    pathList = os.listdir(sorcePath)
    PATH = []
    fileName = []
    i = 0
    for allFile in pathList:
        if allFile[:2] != "~$":
            everyFile = os.path.join(sorcePath, allFile)  # 拼接文件路径
            everyFile = everyFile.replace('\\', '/', 1)  # win执行os.path.join后出现'\\'
            i = i + 1
            PATH.append(everyFile)
            fileName.append(allFile[:-4])

    if not os.path.exists(resultPath):
        os.mkdir(resultPath)


    parallel_enable = 0  # 1: parallel, 0: serial
    if parallel_enable == 1:

        Parallel(n_jobs=-1)(
            delayed(df2xlsx)(path,resultPath) for path in PATH
        )

    else:
        [df2xlsx(path,resultPath) for path in PATH[:]]


if __name__ == "__main__":
    now1 = datetime.now()
    print('start at:', now1)
    cores = os.cpu_count()
    print("CPU core number:", cores)


    typess = ['open', 'boulevard', 'semi-outdoor', 'urban canyon', 'under viaduct', 'shallow indoor', 'deep indoor',
              'transition']
    draw=1  # 1: draw the figures, 0: not draw

    #batchUbx2xlsx('exampleUbxFiles/', 'myExamplexlsx/')
    batchUbx2xlsx('path/to/your/UbxFolder/', 'path/to/your/destinationFolder/')



    now2 = datetime.now()
    time_str = now2.strftime("%Y%m%d%H%M%S")
    print("{} END WITH NO ERROR.".format(now2))
    time_elapsed = now2 - now1
    print("time_elapsed: ", time_elapsed)

